#include "sc.h"
#include "client.h"

int tcpsock; //客户端套接字
int udpsock; //udp客户端套接字
int ret;
static lv_style_t leftstyle;
extern char sendbuf[100];
extern char recvbuf[100];
extern lv_obj_t *scr1;
extern lv_obj_t *scr2;
extern lv_obj_t *scr3;
pthread_t tid; //线程ID
extern void chat_page();
extern struct clientlist *clienthead;//客户端链表头指针
extern lv_obj_t* ta6;


//这个函数用于udp接收服务器发送的数据
void *sc_recv1(void *arg)
{
    char recvbuf[2048];
    while(1)
    {
        bzero(recvbuf,sizeof(recvbuf));
        recvfrom(udpsock,recvbuf,sizeof(recvbuf),0,NULL,NULL);
        printf("recv udp data:%s\n");
		char *a = strtok(recvbuf,"@");//a是Send
		printf("a:%s\n",a);
		if(strcmp(a,"Send") == 0)//表示UDP接受到了聊天信息
		{
		    //表示客户端接收到了聊天信息
			a = strtok(NULL,"@");//a是聊天内容
			printf("客户端说：%s\n",a);
			//将聊天信息在列表中显示
			//创建标签
			lv_obj_t *label = lv_label_create(ta6);
			// //设置样式
			// lv_style_init(&leftstyle);
			// lv_style_set_text_align(&leftstyle, LV_TEXT_ALIGN_LEFT);
			//设置标签大小
			lv_obj_set_size(label, 300, 20);
			//设置标签内容
			lv_label_set_text(label, a);
		}
		else if(strcmp(a,"bq") == 0)//表示UDP接收到了表情包信息
		{
		    //再次切割字符串
			a = strtok(NULL,"@");//a是表情包编号
			printf("表情包编号：%s\n",a);
			if(strcmp(a,"bqone") == 0)
			{
			    //表示收到的是第一个表情包
				//那就将表情包显示在标签上
				//在聊天列表中创建一个标签
				lv_obj_t *label = lv_label_create(ta6);
				//设置标签大小
				lv_obj_set_size(label, 300, 144);
				//将第一个表情包显示在标签上
				//给按钮设置图片源
				lv_obj_t* img2 = lv_img_create(label);
				//设置图片位置
  				lv_obj_set_align(img2, LV_ALIGN_LEFT_MID);
				//声明图片
				LV_IMG_DECLARE(bq1);
				//图片源与图片绑定
				lv_img_set_src(img2, &bq1);
				//将标签滚动到视图
				lv_obj_scroll_to_view(label, LV_ANIM_ON);
			}
			else if(strcmp(a,"bqtwo") == 0)
			{
			    //表示收到的是第二个表情包
				//那就将表情包显示在标签上
				//在聊天列表中创建一个标签
				lv_obj_t *label = lv_label_create(ta6);
				//设置标签大小
				lv_obj_set_size(label, 300, 144);
				//将第一个表情包显示在标签上
				//给按钮设置图片源
				lv_obj_t* img2 = lv_img_create(label);
				//设置图片位置
  				lv_obj_set_align(img2, LV_ALIGN_LEFT_MID);
				//声明图片
				LV_IMG_DECLARE(bq2);
				//图片源与图片绑定
				lv_img_set_src(img2, &bq2);
				//将标签滚动到视图
				lv_obj_scroll_to_view(label, LV_ANIM_ON);
			}
		}
    }
}



//这个函数用于创建客户端并连接服务器
void sc_init()
{
    //定义IPV4地址结构体变量，存放你需要绑定的IP和端口号
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=AF_INET;
	bindaddr.sin_addr.s_addr=htonl(INADDR_ANY);//自动匹配本机ubuntu上的ip，只能在绑定的时候使用
	bindaddr.sin_port=htons(10001); //绑定的端口，由程序员自己指定一个端口号

	struct sockaddr_in bindaddr1;//UDP客户端绑定
	bzero(&bindaddr1,sizeof(bindaddr1));
	bindaddr1.sin_family=AF_INET;
	bindaddr1.sin_addr.s_addr=htonl(INADDR_ANY);//自动匹配本机ubuntu上的ip，只能在绑定的时候使用
	bindaddr1.sin_port=htons(10001); //绑定的端口，由程序员自己指定一个端口号
	
	//定义IPV4地址结构体变量，存放服务器的ip和端口号
	struct sockaddr_in serveraddr;
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_addr.s_addr=inet_addr("192.168.26.129");  //存放服务器的ip地址 
	serveraddr.sin_port=htons(20000);  //服务器的端口号
	
	//第一步：买手机--》创建tcp套接字
	tcpsock=socket(AF_INET,SOCK_STREAM,0);
	if(tcpsock==-1)
	{
		perror("创建tcp套接字失败了!\n");
		return -1;
	}

	udpsock=socket(AF_INET,SOCK_DGRAM,0);
	if(udpsock==-1)
	{
		perror("创建udp套接字失败了!\n");
		return -1;
	}

	//取消端口号绑定限制
	int on=1; //非零值(表示真)
	setsockopt(tcpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	setsockopt(udpsock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
	
	//第二步：绑定ip和端口号
	ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("tcp绑定ip端口号失败了!\n");
		return -1;
	}
	ret=bind(udpsock,(struct sockaddr *)&bindaddr1,sizeof(bindaddr1));
	if(ret==-1)
	{
		perror("udp绑定ip端口号失败了!\n");
		return -1;
	}
	
	//第三步：连接服务器
	ret=connect(tcpsock,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
	if(ret==-1)
	{
		perror("连接服务器失败了!\n");
	}
	//连接成功上了服务器，创建一个线程用于接收服务器发送过来的数据
	pthread_create(&tid,NULL,sc_recv,NULL);
	//创建一个线程，专门用于udp套接字接收信息
	pthread_create(&tid,NULL,sc_recv1,NULL);
}


//这个函数用于tcp接收服务器发送的数据
void *sc_recv(void *arg)
{
    while(1)
    {
        bzero(recvbuf,sizeof(recvbuf));
        ret = recv(tcpsock,recvbuf,sizeof(recvbuf),0);
    	if(ret > 0)
        {
			printf("recv data:%s\n",recvbuf);
			char *a=strtok(recvbuf,"@");
			if(strcmp(recvbuf,"achive")==0)//注册成功
			{
				//表示客户端接收到了注册成功的信息，那就创建一个消息盒子，提示用户注册成功
				lv_obj_t * mbox1 = lv_msgbox_create(scr2,"Register success","Please close the window",NULL,true);
				//把消息盒子放在屏幕中间
				lv_obj_align(mbox1,LV_ALIGN_CENTER,0,0);
			}
			else if(strcmp(recvbuf,"NOMIMA")==0)//注册失败
			{
			    //表示客户端没接收到了登录密码，那就创建一个消息盒子，提示用户没密码
				lv_obj_t * mbox3 = lv_msgbox_create(scr2,"Login success","Please input password",NULL,true);
				//把消息盒子放在屏幕中间
				lv_obj_align(mbox3,LV_ALIGN_CENTER,0,0);
			}
			else if(strcmp(recvbuf,"NOUSR")==0)//没有输入账号
			{
			    lv_obj_t * mbox5 = lv_msgbox_create(scr2,"Login success","Please input username",NULL,true);
				//把消息盒子放在屏幕中间
				lv_obj_align(mbox5,LV_ALIGN_CENTER,0,0);
			}
			else if(strcmp(recvbuf,"fail")==0)//注册失败
			{
				//表示客户端接收到了注册失败的信息，那就创建一个消息盒子，提示用户注册失败
				lv_obj_t * mbox2 = lv_msgbox_create(scr2,"Register failed","Please close the window",NULL,true);
				//把消息盒子放在屏幕中间
				lv_obj_align(mbox2,LV_ALIGN_CENTER,0,0);
			}
			else if(strcmp(recvbuf,"Loginachive")==0)//登录成功
			{
				//表示客户端接收到了登录成功的信息，那就新建一个页面，这个页面是聊天页面
				chat_page();
			}
			else if(strcmp(recvbuf,"Loginerror")==0)//登录失败
			{
				//表示客户端接收到了登录失败的信息，那就创建一个消息盒子，提示用户登录失败
				lv_obj_t * mbox4 = lv_msgbox_create(scr2,"Login failed","Please close the window",NULL,true);
				//把消息盒子放在屏幕中间
				lv_obj_align(mbox4,LV_ALIGN_CENTER,0,0);
				//消息盒子大小
				lv_obj_set_size(mbox4,200,100);
			}
			else if(strcmp(a,"IPandPort")==0)//发过来的是所有客户端信息
			{
				//表示客户端接收到了所有客户端信息
				//继续切割recvbuf
				char ip[50];
				unsigned short port;
				while( (a=strtok(NULL,"@")) != NULL)//切割完了就停了
				{
					//a是客户端的ip地址
					printf("%s\n",a);
					bzero(ip,sizeof(ip));
					if(strlen(a)<sizeof(ip))
					{
					    strcpy(ip,a);//将IP地址存入ip数组中
						a = strtok(NULL,"@");//a是客户端的端口号
						printf("%s\n",a);
						port=atoi(a);//将端口号转换为整型
						//遍历链表，如果这个端口号已经存在了，那就不存储，否则存储
						struct clientlist *p=clienthead;
						while(p->next!=NULL)
						{
							p=p->next;
							if(p->clientport==port)
							{
								//端口号存在了，不存储
								break;
							}
						}
						if(p->next==NULL && port!=p->clientport)//端口号不存在，且不是自己
						{
							//创建一个节点
							struct clientlist *newnode=malloc(sizeof(struct clientlist));
							strcpy(newnode->ipaddr,ip);
							newnode->clientport=port;
							newnode->next=NULL;
							//将节点插入到链表尾部
							p->next=newnode;
							cli_list_show(clienthead);//显示客户端列表
						}
					}
				}
			}
			else if(strcmp(a,"Send")==0)//发过来的是聊天信息
			{
				//表示客户端接收到了聊天信息
				a = strtok(NULL,"@");//a是聊天内容
				bzero(recvbuf,sizeof(recvbuf));
				strcpy(recvbuf,a);
				printf("客户端说：%s\n",recvbuf);
				//将聊天信息在列表中显示
				//创建标签
				lv_obj_t *label = lv_label_create(ta6);
				//设置标签大小
				lv_obj_set_size(label, 350, 20);
				//设置标签内容
				lv_label_set_text(label, recvbuf);
				//将标签滚动到视图
				lv_obj_scroll_to_view(label, LV_ANIM_ON);
			}
			else if(strcmp(a,"ALL")==0)//发过来的是群聊信息
			{
				//表示客户端接收到了群聊信息
				a = strtok(NULL,"@");//a是聊天内容
				printf("a:%s\n",a);
				const char *msg = a;
				//将聊天信息在消息盒子中显示
				lv_obj_t * mbox6 = lv_msgbox_create(scr3,"hello",msg,NULL,true);
				//把消息盒子放在屏幕中间
				lv_obj_align(mbox6,LV_ALIGN_CENTER,0,0);
			}
		}
		
    }
}

void sc_send()
{
	//第四步：发送账号密码给服务器
	ret=send(tcpsock,sendbuf,strlen(sendbuf),0);
	if(ret==-1)
	{
		perror("发送信息给服务器失败了!\n");
		return 0;
	}
}

void sc_close()
{
	//第五步：关闭套接字
	close(tcpsock);
}